package com.systemframework.pay.service.impl;

import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.systemframework.exception.ResultException;
import com.systemframework.pay.config.WxPayProperties;
import com.systemframework.pay.model.PayOrderRequestDTO;
import com.systemframework.pay.service.PayCommon;
import com.systemframework.util.IpKit;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Map;

/**
 * @author summer
 * @date 2023-11-01 9:48
 */
@Service
@AllArgsConstructor
@Slf4j
public class WxPay implements PayCommon {

    private final WxPayService wxPayService;


    @Override
    public String nativePay(PayOrderRequestDTO payOrderRequestDTO, HttpServletRequest request) {
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = getWxPayUnifiedOrderRequest(payOrderRequestDTO);
        wxPayUnifiedOrderRequest.setTradeType(WxPayConstants.TradeType.NATIVE);
        wxPayUnifiedOrderRequest.setSpbillCreateIp(IpKit.getRealIp(request));
        try {
            WxPayNativeOrderResult wxPayNativeOrderResult = wxPayService.createOrder(wxPayUnifiedOrderRequest);
            return QrCodeUtil.generateAsBase64(wxPayNativeOrderResult.getCodeUrl(), new QrConfig(200, 200), "png");
        } catch (Exception e) {
            log.error("error:", e.getMessage(),e);
            throw new ResultException("扫码支付失败");
        }

    }

    @Override
    public Map<String, Object> appPay(PayOrderRequestDTO payOrderRequestDTO) {
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = getWxPayUnifiedOrderRequest(payOrderRequestDTO);
        wxPayUnifiedOrderRequest.setTradeType(WxPayConstants.TradeType.APP);
        try {
            WxPayAppOrderResult wxPayAppOrderResult= wxPayService.createOrder(wxPayUnifiedOrderRequest);
            return JSON.parseObject(JSON.toJSONString(wxPayAppOrderResult),new TypeReference<Map<String,Object>>(){});
        }catch (Exception e){
            throw new ResultException("APP支付失败:"+e.getMessage());
        }

    }

    @Override
    public String h5Pay(PayOrderRequestDTO payOrderRequestDTO, HttpServletRequest request) {
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = getWxPayUnifiedOrderRequest(payOrderRequestDTO);
        wxPayUnifiedOrderRequest.setTradeType(WxPayConstants.TradeType.MWEB);
        wxPayUnifiedOrderRequest.setSpbillCreateIp(IpKit.getRealIp(request));
        try {
            WxPayMwebOrderResult wxPayMwebOrderResult =  wxPayService.createOrder(wxPayUnifiedOrderRequest);
            return wxPayMwebOrderResult.getMwebUrl();
        }catch (Exception e){
            throw new ResultException("h5支付失败:"+e.getMessage());
        }
    }


    private WxPayProperties wxPayProperties;

    @Autowired
    public void setWxPayProperties(WxPayProperties wxPayProperties) {
        this.wxPayProperties = wxPayProperties;
    }

    public WxPayMpOrderResult jsapiPay(PayOrderRequestDTO payOrderRequestDTO, HttpServletRequest request) {
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = getWxPayUnifiedOrderRequest(payOrderRequestDTO);
        wxPayUnifiedOrderRequest.setTradeType(WxPayConstants.TradeType.JSAPI);
        wxPayUnifiedOrderRequest.setAppid(payOrderRequestDTO.getAppId());
        wxPayUnifiedOrderRequest.setOpenid(payOrderRequestDTO.getOpenId());
        wxPayUnifiedOrderRequest.setSpbillCreateIp(IpKit.getRealIp(request));
        try {
            return wxPayService.createOrder(wxPayUnifiedOrderRequest);
        }catch (Exception e){
            throw new ResultException("jsapiPay支付失败:"+e.getMessage());
        }

    }


    private WxPayUnifiedOrderRequest getWxPayUnifiedOrderRequest(PayOrderRequestDTO payOrderRequestDTO){
        WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
        BigDecimal amount = new BigDecimal(payOrderRequestDTO.getProductPrice());
        BigDecimal multiply = amount.multiply(new BigDecimal("100"));
        wxPayUnifiedOrderRequest.setOutTradeNo(payOrderRequestDTO.getOrderNo());
        wxPayUnifiedOrderRequest.setTotalFee(multiply.intValue());
        wxPayUnifiedOrderRequest.setBody(payOrderRequestDTO.getProductName());
        wxPayUnifiedOrderRequest.setProductId(payOrderRequestDTO.getProductId());
        wxPayUnifiedOrderRequest.setNotifyUrl(payOrderRequestDTO.getNotifyUrl());
        return wxPayUnifiedOrderRequest;
    }


    public WxPayOrderNotifyResult notifyResult(String xmlData)  {
        try {
            return wxPayService.parseOrderNotifyResult(xmlData);
        }catch (Exception e){
            throw new ResultException(e.getMessage());
        }

    }
}
